package inteligenciaArtificial;

import java.util.Vector;

import nivel.Coordenada;

import personaje.Enemigo;

/**
 * La clase ControladorEnemigos modela un director que se encarga de controlar
 * los enemigos. Contiene una coleccion en la cual se almacenan, y brinda
 * metodos para actualizarlo. Ademas contiene un metodo que le ordena a los
 * enemigos que realicen un movimiento.
 * 
 * @author Agustin Orge (LU.85538)
 * @author Victoria Martinez de la Cruz (LU.87620)
 */
public class ControladorEnemigos implements Runnable {

	protected Vector<Enemigo> enemigos;
	protected boolean terminarHilo;

	/**
	 * Constructor de la clase Crea la estructura para almacenar los enemigos.
	 */
	public ControladorEnemigos() {
		enemigos = new Vector<Enemigo>();
		terminarHilo = false;
	}

	/**
	 * Agrega un enemigo al final de la coleccion
	 * 
	 * @param e
	 *            - Enemigo a agregar
	 */
	public void agregarEnemigo(Enemigo e) {
		enemigos.add(e);
	}

	/**
	 * Elimina un enemigo de la coleccion segun su coordenada.
	 * 
	 * @param c
	 *            - posicion del enemigo
	 */
	public void eliminarEnemigo(Coordenada c) {
		boolean encontre = false;
		int i = 0;
		while (!encontre && i < enemigos.size()) {
			if (enemigos.get(i).getCasilleroActual().getCoordenada()
					.compareTo(c) == 0) {
				encontre = true;
				enemigos.remove(i);
			}
			i++;
		}
	}

	/**
	 * Busca un enemigo en la coleccion segun su coordenada
	 * 
	 * @param c
	 *            - coordenada a buscar
	 * @return el enemigo que se encuentra en esa posicion null, si no existe
	 *         enemigo con esa posicion
	 */
	public Enemigo buscarEnemigo(Coordenada c) {
		boolean encontre = false;
		Enemigo retorno = null;
		int i = 0;
		while (!encontre && i < enemigos.size()) {
			if (enemigos.get(i).getCasilleroActual().getCoordenada()
					.compareTo(c) == 0) {
				encontre = true;
				retorno = enemigos.get(i);
			}
			i++;
		}
		return retorno;
	}

	/**
	 * Busca un enemigo en la coleccion segun su coordenada.
	 * 
	 * @param c
	 *            - coordenada a buscar
	 * @return el enemigo que se encuentra en esa posicion, o el que se
	 *         encuentra hacia la izquierda, o el que se encuentra hacia la
	 *         derecha, null, si no existe enemigo con esa posicion
	 */
	public Enemigo buscarEnemigoAbajo(Coordenada c) {

		Coordenada abajoIzq, abajoDer;
		abajoIzq = new Coordenada(c.getX() - 8, c.getY());
		abajoDer = new Coordenada(c.getX() + 8, c.getY());
		boolean encontre = false;
		Enemigo retorno = null;
		int i = 0;
		while (!encontre && i < enemigos.size()) {
			if ((enemigos.get(i).getCasilleroActual().getCoordenada()
					.compareTo(c) == 0)
					|| (enemigos.get(i).getCasilleroActual().getCoordenada()
							.compareTo(abajoIzq) == 0)
					|| (enemigos.get(i).getCasilleroActual().getCoordenada()
							.compareTo(abajoDer) == 0)) {
				encontre = true;
				retorno = enemigos.get(i);
			}
			i++;
		}
		return retorno;
	}

	/**
	 * Recorre la coleccion de enemigos, indicandole a cada componente que
	 * realice un movimiento. Controla si hay una colision con mario.
	 */
	private void realizarTickMovimiento() {

		Enemigo aux[] = new Enemigo[enemigos.size()];
		enemigos.toArray(aux);

		for (int i = 0; i < aux.length; i++) {
			Enemigo e = aux[i];
			if (e.getRumbo().equals("derecha")) {
				e.moverDerecha();
			} else {
				e.moverIzquierda();
			}

		}
	}

	/**
	 * Controla si se produjo una colision, en ese caso, mario muere
	 * 
	 * @param e
	 *            - enemigo
	 */
	private void colisionMario(Enemigo e) {
		if (e.getNivel().getMario().getCasilleroActual().getCoordenada()
				.compareTo(e.getCasilleroActual().getCoordenada()) == 0) {
			e.getNivel().getMario().controlQuienMuere(e);
		}
	}

	/**
	 * Recorre la coleccion indicandole a sus componentes que caigan. Controla
	 * si hay colision.
	 */
	public void tickCaer() {
		Enemigo aux[] = new Enemigo[enemigos.size()];
		enemigos.toArray(aux);

		for (int i = 0; i < aux.length; i++) {

			aux[i].caer();

		}

	}

	public void tickBomba(Coordenada c) {
		int posicion = c.getX();
		terminarHilo = true;

		Enemigo aux[] = new Enemigo[enemigos.size()];
		enemigos.toArray(aux);

		for (int i = 0; i < aux.length; i++) {
			int distancia = Math.abs(aux[i].getCasilleroActual().getX()
					- posicion);
			if (distancia >= 0 && distancia <= 336) {

				aux[i].morir();

			}
		}
		terminarHilo = false;
	}

	/**
	 * Metodo utilizado para terminar la ejecucion del hilo con el cual se
	 * ejecuta esta clase.
	 */
	public void terminarHilo() {

		terminarHilo = true;
	}

	public void controlarColisiones() {
		Enemigo aux[] = new Enemigo[enemigos.size()];
		enemigos.toArray(aux);

		for (int i = 0; i < aux.length; i++) {

			Enemigo e = aux[i];
			colisionMario(e);
		}
	}

	@Override
	public void run() {
		while (!terminarHilo) {
			realizarTickMovimiento();

			try {
				Thread.sleep(250);
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
		}

	}

}
